package work.mediway.common.exception;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.StrUtil;
import com.mediway.hos.base.model.BaseResponse;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.TransientDataAccessResourceException;
import org.springframework.http.HttpStatus;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import work.mediway.common.domain.enums.CodeAndMsgEnum;

import java.sql.SQLException;
import java.sql.SQLIntegrityConstraintViolationException;

/**
 * 全局异常捕获<br>
 *
 * @author zhongyj
 * @date 2019/7/1
 */
@Slf4j
@Order(value = Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
@RestControllerAdvice
public class CdrMpGlobalExceptionHandler extends BaseExceptionHandler {

    /**
     * SQL异常
     *
     * @param e SQLException
     * @return ResponseVO
     */
    @ExceptionHandler(TransientDataAccessResourceException.class)
    @ResponseStatus(HttpStatus.OK)
    public BaseResponse handlerException(TransientDataAccessResourceException e) {
        this.buildErrorInfo("SQL执行异常", e);
        if (StrUtil.containsAnyIgnoreCase(e.getMessage(), "在被引用的表中DELETE行时,外键约束未通过引用检查")) {
            return BaseResponse.error(String.valueOf(CodeAndMsgEnum.FAIL.getCode()), "删除该数据时，该数据被其他数据引用，删除失败");
        }
        if (StrUtil.containsAnyIgnoreCase(e.getMessage(), "在引用表中INSERT行时,外键约束未通过引用检查", "在引用表中插入行时,外键约束未通过引用检查")) {
            return BaseResponse.error(String.valueOf(CodeAndMsgEnum.FAIL.getCode()), "新增或者更新时,关联外键数据不存在,操作失败");
        }
        if (StrUtil.containsAnyIgnoreCase(e.getMessage(), "INSERT时,唯一或主键约束未通过唯一性检查", "唯一或主键约束未通过唯一性检查")) {
            return BaseResponse.error(String.valueOf(CodeAndMsgEnum.FAIL.getCode()), "插入数据时,其主键字段不能重复");
        }
        return BaseResponse.error(String.valueOf(CodeAndMsgEnum.FAIL.getCode()), e.getMessage());
    }

    @ExceptionHandler(BadSqlGrammarException.class)
    @ResponseStatus(HttpStatus.OK)
    public BaseResponse handlerException(BadSqlGrammarException e) {
        this.buildErrorInfo("SQL执行异常", e);
        return BaseResponse.error(String.valueOf(CodeAndMsgEnum.FAIL.getCode()), e.getMessage());
    }

    @ExceptionHandler(DataIntegrityViolationException.class)
    @ResponseStatus(HttpStatus.OK)
    public BaseResponse handlerException(DataIntegrityViolationException e) {
        this.buildErrorInfo("SQL执行异常", e);

        if (StrUtil.containsAnyIgnoreCase(e.getMessage(), "缺少所需字段;不允许INSERT或更新", "缺少所需字段;不允许插入或更新")) {
            return BaseResponse.error(String.valueOf(CodeAndMsgEnum.SERVER_ERROR.getCode()), "新增或者更新时,数据的完整性验证未通过,必填字段为空");
        }
        return BaseResponse.error(String.valueOf(CodeAndMsgEnum.SERVER_ERROR.getCode()), e.getMessage());
    }

    @ExceptionHandler(MyBatisSystemException.class)
    @ResponseStatus(HttpStatus.OK)
    public BaseResponse handlerException(MyBatisSystemException e) {
        if (StrUtil.containsAnyIgnoreCase(e.getMessage(), "work.mediway.mdm.core.exception.DataException: 日志记录失败")) {
            return BaseResponse.error(String.valueOf(CodeAndMsgEnum.SERVER_ERROR.getCode()), "数据操作失败, 请重试");
        }
        return BaseResponse.error(String.valueOf(CodeAndMsgEnum.SERVER_ERROR.getCode()), e.getMessage());
    }

    @ExceptionHandler(SQLException.class)
    public BaseResponse<String> mySqlException(SQLException e) {
        if (e instanceof SQLIntegrityConstraintViolationException) {
            return BaseResponse.error("该数据有关联数据或数据已存在，操作失败");
        }
        e.printStackTrace();
        log.error("数据库异常: 【{}】", ExceptionUtil.stacktraceToString(e));
        return BaseResponse.error("数据库异常，操作失败");
    }


}













